package net.hands.common.web.html.js;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;

import net.hands.common.IoUtils;
import net.hands.common.StringUtils;
import net.hands.common.logger.Log;
import net.hands.common.logger.LogFactory;

/**
 * 说明:js脚本工具类
 * <br>
 * <p>这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。</p>
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public abstract class JavascriptUtils {
	static Log log = LogFactory.getLogger(JavascriptUtils.class);
   /**
   * 说明:特殊字符转义替换   于net.simpleframework.common.html.simulate.HtmlSimulate.htmlToHtml(String)方法前使用
   * @param input 源字符
   * @return  String 替换后字符
   * @update 2012-9-20 下午12:28:33
    */
	public static String escape(final String input) {
		if (input == null) {
			return input;
		}
		final StringBuilder filtered = new StringBuilder(input.length());
		char prevChar = '\u0000';
		char c;
		for (int i = 0; i < input.length(); i++) {
			c = input.charAt(i);
			if (c == '"') {
				filtered.append("\\\"");
			} else if (c == '\'') {
				filtered.append("\\'");
			} else if (c == '\\') {
				filtered.append("\\\\");
			} else if (c == '/') {
				filtered.append("\\/");
			} else if (c == '\t') {
				filtered.append("\\t");
			} else if (c == '\n') {
				if (prevChar != '\r') {
					filtered.append("\\n");
				}
			} else if (c == '\r') {
				filtered.append("\\n");
			} else if (c == '\f') {
				filtered.append("\\f");
			} else {
				filtered.append(c);
			}
			prevChar = c;
		}
		return filtered.toString();
	}
   /**
    * 是否使用压缩 前提是加载yahoo的yui.jar包
    */
	static boolean compressorEnabled = false;
	static {
		try {
			//找到压缩类
			Class.forName("com.yahoo.platform.yui.compressor.JavaScriptCompressor");
			//使用压缩
			compressorEnabled = true;
		} catch (final Exception ex) {
			//不使用压缩
			log.warn("Javascript compressor disabled!");
		}
	}
   /**
   * 说明:js 压缩
   * @param js js脚本
   * @return String
   * @update 2012-9-20 下午12:33:03
    */
	public static String jsCompress(final String js) {
		if (!compressorEnabled) {//判定是都压缩
			return js;
		}
		
		final StringWriter oWriter = new StringWriter();
		try {
			//压缩js
			new com.yahoo.platform.yui.compressor.JavaScriptCompressor(new StringReader(js), null)
					.compress(oWriter, -1, true, false, false, false);
			//压缩后输出
			return oWriter.toString();
		} catch (final Throwable e) {
			return js;
		} finally {
			try {
				oWriter.close();
			} catch (final IOException e) {
			}
		}
	}
   /**
    * 说明:外包$ready方法  $ready(function() {functionBody});
   * @param functionBody 方法体
   * @return String  
   * @update 2012-9-20 下午12:58:10
    */
	public static String wrapWhenReady(final String functionBody) {
		final StringBuilder sb = new StringBuilder();
		sb.append("$ready(function() {").append(StringUtils.blank(functionBody)).append("});");
		return sb.toString();
	}
   /**
    * 说明:外包function()方法   (function() {functionBody})();
   * @param functionBody 方法体
   * @return String
   * @update 2012-9-20 下午12:59:35
    */
	public static String wrapFunction(final String functionBody) {
		final StringBuilder sb = new StringBuilder();
		sb.append("(function() {").append(StringUtils.blank(functionBody)).append("})();");
		return sb.toString();
	}
   /**
   * 说明:参数外包js脚本引入  如<script Type=\"text/javascript\">javascript</script>
   * @param javascript js脚本
   * @return String
   * @update 2012-9-20 下午1:00:26
    */
	public static String wrapScriptTag(final String javascript) {
		final StringBuilder sb = new StringBuilder();
		sb.append("<script Type=\"text/javascript\">").append(StringUtils.blank(javascript));
		sb.append("</script>");
		return sb.toString();
	}
   /**
   * 说明:拷贝文件
   * @param inputStream 输入流
   * @param to 目标文件
   * @param jsCompress  是否压缩js
   * @param cssCompress 是否压缩css
   * @throws IOException
   * @update 2012-9-20 下午1:01:17
    */
	public static void copyFile(final InputStream inputStream, final File to,
			final boolean jsCompress, final boolean cssCompress) throws IOException {
		if (!compressorEnabled) {//是都压缩
			IoUtils.copyFile(inputStream, to);//拷贝文件
			return;
		}
		final String filename = to.getName();//获得文件名
		if ((jsCompress && filename.endsWith(".js")) || (cssCompress && filename.endsWith(".css"))) {//是都是js 或css 
			OutputStreamWriter oWriter = null;
			String c = null;
			try {
				c = IoUtils.getStringFromInputStream(inputStream);//流转字符
				if (!to.exists()) {//文件是否存在
					IoUtils.createFile(to);//不存在创建文件
				}
				//写入流
				oWriter = new OutputStreamWriter(new FileOutputStream(to));
				//文件是js开始
				if (filename.endsWith(".js")) {
					//用js压缩字符到文件
					new com.yahoo.platform.yui.compressor.JavaScriptCompressor(new StringReader(c), null)
							.compress(oWriter, 200, true, false, false, false);
				} else {
					//用css压缩字符到文件
					new com.yahoo.platform.yui.compressor.CssCompressor(new StringReader(c)).compress(
							oWriter, 200);
				}
			} catch (final Exception e) {
				if (c != null) {
					IoUtils.copyFile(new ByteArrayInputStream(c.getBytes()), to);
				}
			} finally {
				if (oWriter != null) {
					oWriter.close();
				}
			}
		} else {
			//拷贝流到文件中
			IoUtils.copyFile(inputStream, to);
		}
	}
}
